#include "Main.h"


ServicesBuilder::ServicesBuilder()
{
	cout << "[ServicesBuilder] Constructor Called" << "\n";

	MappedCommandValues["url"]		= evCommandValue01;
	MappedCommandValues["md5"]		= evCommandValue02;
	MappedCommandValues["extract-cmd"]	= evCommandValue03;
	MappedCommandValues["directory"]	= evCommandValue04;
	MappedCommandValues["cleanup"]		= evCommandValue05;
	MappedCommandValues["end"]		= evCommandEnd;
	
}

ServicesBuilder::~ServicesBuilder()
{
	cout << "[ServicesBuilder] Destructor Called" << "\n";
}

bool ServicesBuilder::RunCommand(char * cmd_ini_name, CommandRunner * cmdstruct) {

	FILE *			fp;
	HyperTextTransfer *	http ;
	char			aName[256] ;
	char            	cName[256] ;
	char            	uName[256] ;
	char            	pName[1024] ;
	bool                    success = true;

	memset(cName, 0x0, strlen(cName));
	switch(MappedCommandValues[cmd_ini_name])
	{
		case evCommandValue01:

		        sprintf(aName, "%s:url", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, cmdstruct->softwarename, NULL));
		        sprintf(uName, "%s", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, aName, NULL));
		        
		        http = new HyperTextTransfer();
		        cmdstruct->UrlFileInfo = http->PerformDownload(uName);
		        delete http;
		        
			break;
		case evCommandValue02:

			sprintf(aName, "%s:md5", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, cmdstruct->softwarename, NULL));
			sprintf(uName, "%s", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, aName, NULL));

			if (strcmp(cmdstruct->UrlFileInfo.md5, uName) != 0) {
				cout << "MD5 checksum does not match that of what is in the configuration" << endl;
				success = false;
			} else {
			        cout << "MD5 checksums are correct" << endl;
			}

			break;
		case evCommandValue03:

			sprintf(aName, "%s:extract-cmd", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, cmdstruct->softwarename, NULL));
			sprintf(uName, "%s", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, aName, NULL));
			sprintf(cName, "%s %s", uName, cmdstruct->UrlFileInfo.file);

			break;
		case evCommandValue04:

			sprintf(aName, "%s:directory", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, cmdstruct->softwarename, NULL));
		        sprintf(uName, "%s/%s", cmdstruct->path, cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, aName, NULL));

		        cout << "Command:\t[cd " << uName << "]" << endl;
	                if (chdir(uName) != 0) {
				cout << "Failed to change directory" << endl;
				success = false;
	                }

			break;
		case evCommandValue05:

			sprintf(aName, "%s:cleanup", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, cmdstruct->softwarename, NULL));
			sprintf(uName, "%s", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, aName, NULL));

			for (int i = 0; uName[i]; i++) {
				uName[i] = tolower(uName[i]);
			}

			if (strcmp(uName, "true") == 0) {
			
			        memset(aName, 0x0, strlen(aName));
			        memset(uName, 0x0, strlen(uName));

				sprintf(aName, "%s:directory", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, cmdstruct->softwarename, NULL));
				sprintf(uName, "%s", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, aName, NULL));
				sprintf(cName, "rm -Rf %s %s", uName, cmdstruct->UrlFileInfo.file);

			}

		        break;
		default:

			sprintf(aName, "%s:%s", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, cmdstruct->softwarename, NULL), cmd_ini_name);
			if (cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, aName, NULL) == NULL) {
			        success = false;
				break;
			}
          		sprintf(cName, "%s", cmdstruct->iniparse->iniparser_getstring(cmdstruct->inidict, cmdstruct->ini, aName, NULL));

			break;
	}
	
	if ((strlen(cName) != 0) && (success != false)) {

		cout << "Command:\t[" << cName << "]" << endl;

		fp = popen(cName, "r");
		if (fp == NULL) {
			success = false;
		} else {

			/* Read the output a line at a time - output it. */
			while (fgets(pName, sizeof(pName) - 1, fp) != NULL) {
				cout << pName;
			}

			/* close */
			pclose(fp);

		}

	}
	
	return success;

}

int ServicesBuilder::RunConfiguration(char * ini_name, int pCount) {

        
	CommandRunner		cmdstruct ;
	int			iCount ;
	int             	oCount ;
	char            	nName[8];
	char *                  path = NULL;
	size_t			size;

	cmdstruct.ini = cmdstruct.iniparse->iniparser_load(cmdstruct.inidict, ini_name);
	if (cmdstruct.ini == NULL) {
		fprintf(stderr, "cannot parse file: %s\n", ini_name);
		return -1 ;
	}
	// cmdstruct.iniparse->iniparser_dump(ini, stderr);
	
	// Get current working directory
	cmdstruct.path = getcwd(path, size);
	cout << "Current Working Directory:\t" << cmdstruct.path << "" << endl;

	/* Get pizza attributes */
	for(iCount = pCount; iCount != (cmdstruct.iniparse->iniparser_getint(cmdstruct.inidict, cmdstruct.ini, "SoftwareList:0", 0) + 1); iCount++) {

	        memset(cmdstruct.softwarename, 0x0, strlen(cmdstruct.softwarename));
	        sprintf(cmdstruct.softwarename, "SoftwareList:%d", iCount);

		/** download tar file */
                if (RunCommand("url", &cmdstruct) == false) {
                        break;
                }

                /** if md5 match check if true then perform the commands */
                if (RunCommand("md5", &cmdstruct) == false) {
                        break;
                }
                
                /** extract tar file */
                if (RunCommand("extract-cmd", &cmdstruct) == false) {
                        break;
                }
                
                /** change directory */
                if (RunCommand("directory", &cmdstruct) == false) {
                        break;
                }

		/** print off some information about the file */
	        /** cout << cmdstruct.UrlFileInfo.protocol << "://" << cmdstruct.UrlFileInfo.host << ":" << cmdstruct.UrlFileInfo.port << cmdstruct.UrlFileInfo.path << "#" << cmdstruct.UrlFileInfo.file << endl;
		cout << "File Name:\t" << cmdstruct.UrlFileInfo.file << endl;
		cout << "File Size:\t" << cmdstruct.UrlFileInfo.size << " bytes" << endl;
		cout << "File MD5:\t" << cmdstruct.UrlFileInfo.md5 << endl; */

		for (oCount = 0; oCount != 30; oCount++) {

			/** run listed command */
			sprintf(nName, "%d", oCount);
			if (RunCommand(nName, &cmdstruct) == false) {
			        break;
			}

		}

                chdir(cmdstruct.path);
                /** attempt to remove old directory & tar file */
                if (RunCommand("cleanup", &cmdstruct) == false) {
                        break;
                }

                cout << endl;

	}

	printf("Done!\n");
	cmdstruct.iniparse->iniparser_freedict(cmdstruct.inidict, cmdstruct.ini);
	return 0 ;
}

int main(int argc, char * argv[])
{

        ServicesBuilder *	ServBuilder;
	int			step = 1;

	if (argc == 2) {
                step = atoi(argv[1]);
	}

        ServBuilder = new ServicesBuilder();
	ServBuilder->RunConfiguration("config.cfg", step);

	delete(ServBuilder);

	return 0;
}
